package com.shop.service;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.shop.annotation.RedisLock;
import com.shop.config.MiniAppLoginRequest;
import com.shop.entity.*;
import com.shop.mapper.CommonUserMapper;
import com.shop.mapper.UserMapper;
import com.shop.model.Const;
import com.shop.model.PageParam;
import com.shop.model.dto.Authorization;
import com.shop.model.vo.Rsp;
import com.shop.utils.JasyptUtils;
import lombok.AllArgsConstructor;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
public class UserService {
    private final CommonUserMapper userDao;
    private final RedisService redisService;
    private final WxMaService wxMaService;
    private final UserMapper userMapper;

    /**
     * 用户的登录方法
     *
     * @param user 前端传来的用户
     * @return 返回登录状态
     */
    public Rsp login(CommonUser user) {
        CommonUser login = userDao.getByAccount(user.getAccount());
        if (login == null) {
            return Rsp.fail().msg("账号不存在");
        }
        if (!login.getPassword().equals(user.getPassword())) {
            return Rsp.fail().msg("密码错误");
        }
        if (login.getStatus().equals("1")) {
            return Rsp.fail().msg("用户被锁定联系平台管理员");
        }
        Authorization<?> value;
        login.setPassword(null);
        //登录成功后将用户保存到redis中
        //商家信息
        if (login.getRole().equals("merchant")) {
            MerchantMerchant merchant = userDao.getMerchantByUserId(login.getId());
            value = new Authorization<>(login, merchant);
            //供应商信息
        } else if (login.getRole().equals("supplier")) {
            SupplierSupplier supplier = userDao.getSupplierByUserId(login.getId());
            value = new Authorization<>(login, supplier);
            //平台账号信息
        } else if (login.getRole().equals("platform")) {
            value = new Authorization<>();
            value.setUser(login);
            //其它员工信息
        } else {
            MerchantEmployee employee = userDao.getEmployeeByUserId(login.getId());
            value = new Authorization<>(login, employee);
        }
        String key = login.getRole() + ":" + login.getId();
        redisService.set(key, value, System.currentTimeMillis() / 1000 + Const.expireTime);
        return Rsp.success(JasyptUtils.encryptPwd(key));
    }

    /**
     * 获取用户信息
     *
     * @param token 前端传过来的token
     * @return 返回用户信息
     */
    public Rsp getUserInfo(String token) {
        token = token.replaceAll(" ", "+");
        String key = JasyptUtils.decryptPwd(token);
        Authorization user = (Authorization) redisService.get(key);
        if (user == null) {
            return Rsp.fail().code(50008).msg("重新登录");
        }
        return Rsp.success(user.getUser());
    }

    /**
     * 微信小程序的登录方法
     *
     * @param request 前端传过来的用户信息
     * @return 返回登录状态
     */
    @RedisLock(lockName = "login", key = "#request.code")
    public Rsp miniAppLogin(MiniAppLoginRequest request) {
        WxMaJscode2SessionResult sessionInfo = null;
        try {
            sessionInfo = wxMaService.getUserService().getSessionInfo(request.getCode());
        } catch (WxErrorException e) {
            e.printStackTrace();
            return Rsp.fail().msg("微信登录接口异常");
        }
        if (sessionInfo == null) {
            return Rsp.fail().msg("微信登录接口异常");
        }
        //查找数据库中有没有
        User user = userMapper.selectByOpenId(sessionInfo.getOpenid());
        if (user == null) {
            //获取用户信息并将用户保存到数据库中
            WxMaUserInfo userInfo = wxMaService.getUserService().getUserInfo(sessionInfo.getSessionKey(),
                    request.getEncryptedData(), request.getIv());
            if (userInfo == null) {
                return Rsp.fail().msg("微信登录接口异常");
            }

            User login = new User(userInfo.getNickName(), userInfo.getGender(),
                    userInfo.getAvatarUrl(), userInfo.getOpenId(), sessionInfo.getUnionid());
            login.insert();
            user = login;
        }
        String key = "user:" + user.getId();
        redisService.set(key, user, Const.expireTime);
        return Rsp.success(JasyptUtils.encryptPwd(key));
    }

    public Rsp getMerchantId(Integer userId) {
        return Rsp.success(1);
        // return Rsp.success(userDao.getMerchantByUserId(userId).getId());
    }

    /**
     * 剔除下线
     */
    public Rsp kickOutById(CommonUser user) {
        String key = user.getRole() + ":" + user.getId();
        redisService.remove(key);
        return Rsp.success(null);
    }

    /**
     * 退出当前用户
     *
     * @param token
     * @return
     */
    public Rsp logout(String token) {
        String key = JasyptUtils.decryptPwd(token);
        redisService.remove(key);
        return Rsp.success(null).msg("登出成功");
    }

    public Rsp getAllUser(PageParam<CommonUser> pageParam) {
        PageHelper.startPage(pageParam.getPageNum(), pageParam.getPageSize());
        List<CommonUser> list = userDao.getAllUser(pageParam.getModel().getStatus());
        list.removeIf(e -> e.getRole().equals("platform"));
        list.forEach(e -> {
            Object o = redisService.get(e.getRole() + ":" + e.getId());
            e.setPassword("");
            if (StringUtils.isEmpty(o)) {
                e.setIsLogin("0");
            } else {
                e.setIsLogin("1");
            }
        });
        if (!StringUtils.isEmpty(pageParam.getModel().getIsLogin())) {
            list = list.stream()
                    .filter(e -> e.getIsLogin().equals(pageParam.getModel().getIsLogin()))
                    .collect(Collectors.toList());
        }
        return Rsp.success(new PageInfo<>(list));
    }

    public Rsp updateStatus(CommonUser user) {
        user.updateById();
        return Rsp.success(null);
    }
}
